package com.zjht.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smartbit.kryojredis.JCache;
import org.smartbit.kryojredis.JRedisSerializationUtils;

import com.zjht.account.common.merchant.dao.TicketDao;
import com.zjht.account.common.merchant.model.Ticket;
import com.zjht.service.DatabaseSynchronizationService;
import com.zjht.utils.MapCacheManager;

import redis.clients.jedis.Jedis;

/**
 * @author Eirui
 *
 */
public class DatabaseSynchronizationServiceImpl implements DatabaseSynchronizationService {

    private static Logger   log             = LoggerFactory.getLogger(DatabaseSynchronizationServiceImpl.class);

    private static Integer  START_RECORD    = 0;

    private MapCacheManager mapCacheManager = MapCacheManager.getInstance();

    private TicketDao       ticketDao       = null;

    @Resource
    private JCache          jCache;


    public void setTicketDao(TicketDao ticketDao) {
        this.ticketDao = ticketDao;
    }

    @Override
    public void ticketSynchronization() {
        log.info("==Method ticketSynchronization to redis start==");
        List<Ticket> ticketGroup = ticketDao.findTicketListByStart(START_RECORD);
        int ticketGroupSize = ticketGroup.size();
        if (isNotNull(ticketGroupSize)) {
            START_RECORD += ticketGroupSize;
            log.info("Search [{}]pcs not import to Redis", ticketGroupSize);
            log.info("Start to import into Redis");
            long startTime = System.currentTimeMillis();
            updateToRedis(ticketGroup);
            long endTime = System.currentTimeMillis();
            log.info("Import success,[{}]ms", (endTime - startTime));
        } else {
            log.info("Can't not find new record");
        }
        log.info("Redis record:[{}]pcs", jCache.getDbSize());
    }

    private void updateToRedis(List<Ticket> ticketGroup) {
        Jedis jedis = jCache.getJedis();
        for (Ticket ticket : ticketGroup) {
            if (jedis.exists(ticket.getAssisCode().getBytes())) {
                continue;
            }
            try {
                jedis.set(ticket.getAssisCode().getBytes(), JRedisSerializationUtils.kryoSerialize(ticket));
            } catch (Exception ex) {
                jCache.coverException(ex, jedis);
            }
        }
        if (jedis != null && jedis.isConnected()) {
            jCache.returnResource(jedis);
        }
    }

    @Override
    public void ticketSynchronizationToDatabase() {
        log.info("==Method ticketSynchronizationToDatabase start==");
        Map<String, Object> ticketCacheMap = getTicketCacheMap();
        int ticketCacheMapSize = ticketCacheMap.size();
        log.info("The ticketCacheMap have [{}]pcs", ticketCacheMapSize);
        if (isNotNull(ticketCacheMapSize)) {
            Set<String> ticketKeys = ticketCacheMap.keySet();
            updateToDatabase(ticketKeys);
        }
    }

    private void updateToDatabase(Set<String> ticketKeys) {
        for (String assistCode : ticketKeys) {
            Ticket cacheTicket = (Ticket) mapCacheManager.getCacheObject(assistCode);
            try {
                ticketDao.update(cacheTicket);
                mapCacheManager.removeCacheObject(assistCode);
                log.info("AssistCode:[{}],Asynchronous update successfully", assistCode);
            } catch (Throwable t) {
                log.info("AssistCode:[{}],Asynchronous update fail", assistCode);
                log.error("Error Message", t);
            }
        }
    }

    private Map<String, Object> getTicketCacheMap() {
        Map<String, Object> ticketCacheMap = new HashMap<String, Object>();
        try {
            ticketCacheMap = mapCacheManager.getMapCache();
        } catch (Exception e) {
            log.error("TicketCacheMap error", e);
        }
        return ticketCacheMap;
    }

    private boolean isNotNull(int objectSize) {
        boolean isFlag = false;
        if (objectSize > 0) {
            isFlag = true;
        }
        return isFlag;
    }

    @Override
    public void reloadDataToRedis() {
        log.info("==Method reloadDataToRedis start==");
        START_RECORD = 0;
        String replyCode = jCache.flushDB();
        log.info("ReloadDataToRedis replyCode:[{}],START_RECORD:[{}]", replyCode, START_RECORD);
    }

}
